﻿#pragma once

#include <cstdint>
#include <set>
#include <stdexcept>
#include <string>
#include <vector>

#include "asycipc/frame.hpp"
#include "asycipc/session_context.hpp"

namespace asycipc {

struct HandshakeRequest {
  std::string app_id;
  uint8_t protocol_version = kProtocolVersion;
  std::vector<std::string> capabilities;
  uint32_t heartbeat_interval_seconds = 5;
};

struct HandshakeResponse {
  std::string session_id;
  uint64_t initial_seq = 1;
  std::string resume_token;
};

struct HandshakeConfig {
  std::string endpoint_name;
  uint8_t protocol_version = kProtocolVersion;
  std::set<std::string> allowed_app_ids;
  uint32_t default_heartbeat_interval = 5;
};

class HandshakeError : public std::runtime_error {
 public:
  using std::runtime_error::runtime_error;
};

class HandshakeManager {
 public:
  explicit HandshakeManager(HandshakeConfig config);

  HandshakeResponse Negotiate(const HandshakeRequest& request,
                              SessionContext& session);

 private:
  HandshakeConfig config_;
  uint64_t session_counter_ = 0;
};

}  // namespace asycipc
